[小ネタ][Golang]go-linqでLINQ風の検索をしてみた
go-linq という LINQ 風に検索できるライブラリを試してみました。使い方自体は go-linq のREADMEを見れば分かったのですが、自分なりにも試してみたいと思い、以前 紹介した gofakeit と組み合わせサンプルプログラムを書いてみました。
以下、そのサンプルプログラムについてとなります。
プログラムと実行について
Golangを実行できる環境にて、「go get」で予め使用するライブラリをインストールしておきます。
$ go get github.com/brianvoe/gofakeit/v6 $ go get github.com/ahmetb/go-linq/v3
今回書いたプログラムは以下となります。以前と同様「gofakeit」でビールに関するダミーデータを作り、そのデータから「go-linq」を使ってビールのモルト(Malt)数での逆ソート、モルト毎のカウントをやってみました。
package main import ( "fmt" "strings" . "github.com/ahmetb/go-linq/v3" "github.com/brianvoe/gofakeit" ) type Beer struct { ID int `csv:"id"` Malt string `csv:"malt"` Name string `csv:"name"` Style string `csv:"style"` } func main() { gofakeit.Seed(0) var beers []Beer for i := 0; i < 10; i++ { b := &Beer{ gofakeit.Number(1, 100), gofakeit.BeerMalt(), gofakeit.BeerName(), gofakeit.BeerStyle(), } beers = append(beers, *b) } for _, b := range beers { fmt.Printf("id : %v, malt : %s, name : %s\n", b.ID, b.Malt, b.Name) } var malts []string From(beers). Select(func(b interface{}) interface{} { return b.(Beer).Malt }). GroupBy( func(malt interface{}) interface{} { return malt }, func(malt interface{}) interface{} { return malt }). OrderByDescending( func(g interface{}) interface{} { return len(g.(Group).Group) }). Select( func(g interface{}) interface{} { return g.(Group).Key }). ToSlice(&malts) for _, m := range malts { c := From(beers).Where(func(b interface{}) bool { return strings.Contains(b.(Beer).Malt, m) }).Select(func(b interface{}) interface{} { return b.(Beer).Name }).Count() fmt.Printf("malt = %s, count = %v\n", m, c) } }
19〜30行目で「gofakeit」を使ってダミーデータを生成しています。この辺りは以前とかわっておりません。「go-linq」を使った検索は36行目以降となります。36〜55行目で、ビール毎のモルト(Malt)の数で逆順でソートしています。構文的にはループを使わず「GroupBy()」や「OrderByDescending()」を使って検索していることが分かるかと思います。次に58〜62行目で、モルト(Malt)毎のカウントを行なっております。こちらもモルト毎のカウント自体にはループを使わず「Count()」を使っております。
実行してみると、以下のように生成したダミーデータ、モルト(Malt)数の逆順でカウントした結果が出力されます。(※ダミーデータはランダムで生成となるので毎回実行結果は異なります)
id : 5, malt : Victory, name : Péché Mortel id : 36, malt : Roasted barley, name : Yeti Imperial Stout id : 89, malt : Rye malt, name : Maudite id : 83, malt : Vienna, name : La Fin Du Monde id : 48, malt : Caramel, name : Sublimely Self-Righteous Ale id : 57, malt : Rye malt, name : Founders Kentucky Breakfast id : 64, malt : Special roast, name : Sierra Nevada Celebration Ale id : 19, malt : Special roast, name : Samuel Smith’s Imperial IPA id : 33, malt : Rye malt, name : Maharaj id : 31, malt : Chocolate malt, name : Storm King Stout malt = Rye malt, count = 3 malt = Special roast, count = 2 malt = Caramel, count = 1 malt = Chocolate malt, count = 1 malt = Victory, count = 1 malt = Roasted barley, count = 1 malt = Vienna, count = 1
sliceに複数件持たせたデータからの検索やカウントという良くある処理について、「Select()」「Groupby()」などで絞り込んでいけることが新鮮でした。何かの役に立てば幸いです。